#ifndef PBVP_BETTI_NUMBER_H
#define PBVP_BETTI_NUMBER_H

#include <stdio.h>
#include <iostream>
#include <algorithm>

namespace PBVP {
	/**
	*	Betti number of surfaces
	*/
	class BettiNumber {
	public:
		int b0, b1, b2;

		BettiNumber() {
			b0 = b1 = b2 = 0;
		}

		/// Copy constructor
		BettiNumber(const BettiNumber& betti) {
			b0 = betti.b0;
			b1 = betti.b1;
			b2 = betti.b2;
		}

		/// assignment operator
		BettiNumber& operator = (const BettiNumber& betti) {
			if (this == &betti) return *this;
			b0 = betti.b0;
			b1 = betti.b1;
			b2 = betti.b2;
			return *this;
		}

		/// += operator
		const BettiNumber& operator += (const BettiNumber& bn) {
			b0 += bn.b0;
			b1 += bn.b1;
			b2 += bn.b2;
			return *this;
		}

		/// -= operator
		const BettiNumber& operator -= (const BettiNumber& bn) {
			b0 -= bn.b0;
			b1 -= bn.b1;
			b2 -= bn.b2;
			return *this;
		}

		/*
		*	Similarity between two set of Betti numbers 
		*/
		float simil(const BettiNumber& betti) {
			float s0, s1, s2;

			s0 = (std::max(b0, betti.b0) == 0)? 1.0f : std::min(b0, betti.b0) / (float)(std::max(b0, betti.b0));
			s1 = (std::max(b1, betti.b1) == 0)? 1.0f : std::min(b1, betti.b1) / (float)(std::max(b1, betti.b1));
			s2 = (std::max(b2, betti.b2) == 0)? 1.0f : std::min(b2, betti.b2) / (float)(std::max(b2, betti.b2));

			return 0.5f*s0 + 0.3f*s1 + 0.2f*s2;
		}

		friend float simBetti(const BettiNumber& bn1, const BettiNumber& bn2) {
			float s0, s1, s2;

			s0 = (std::max(bn1.b0, bn2.b0) == 0)? 1.0f : std::min(bn1.b0, bn2.b0) / (float)(std::max(bn1.b0, bn2.b0));
			s1 = (std::max(bn1.b1, bn2.b1) == 0)? 1.0f : std::min(bn1.b1, bn2.b1) / (float)(std::max(bn1.b1, bn2.b1));
			s2 = (std::max(bn1.b2, bn2.b2) == 0)? 1.0f : std::min(bn1.b2, bn2.b2) / (float)(std::max(bn1.b2, bn2.b2));

			return 0.5f*s0 + 0.3f*s1 + 0.2f*s2;
		}

		friend std::ostream& operator << (std::ostream& os, const BettiNumber& bn) {
			os << bn.b0 << " " << bn.b1 << " " << bn.b2 << " ";
			return os;
		}

		friend std::istream& operator >> (std::istream& is, BettiNumber& bn) {
			is >> bn.b0;
			is >> bn.b1;
			is >> bn.b2;
			return is;
		}

		void print() const {
			printf("B0 = %d, B1 = %d, B2 = %d\n", b0, b1, b2);
		}
	};
}
#endif